<?php

namespace app\admin\service\login;

use app\common\cache\AdminAccountSafeCache;
use app\common\model\auth\AdminRole;
use app\common\model\auth\SystemRole;
use app\admin\service\AdminTokenService;
use app\admin\service\OperationService;
use tmcore\base\BaseService;
use app\common\model\auth\Admin;
use tmcore\exceptions\ValidateException;
use tmcore\services\CaptchaService;

/**
 * 登录服务类
 */
class LoginService extends BaseService
{
    /**
     * 管理员账号登录
     * @param $params
     * @return bool|array
     */
    public static function login($params)
    {

        $adminInfo = self::verify($params['account'], $params['password']);

        // 验证码检验
        if(!empty($params['captchaUniqid']) && !empty($params['code']))CaptchaService::codeVerify($params);

        //设置token
        $tokenInfo = AdminTokenService::setToken($adminInfo['id'], $params['channel'], $adminInfo['multipoint_login']);

        $time = time();

        //管理员数据更新
        Admin::where(['id' => $adminInfo['id']])->update([
            'login_time' => $time,
            'login_ip' => request()->ip()
        ]);

        $result = [
            'name' => $adminInfo['name'],
            'token' => $tokenInfo['token']
        ];

        //添加操作记录
        (new OperationService)->addOperation(request(), $adminInfo, ['code' => 0, 'data' => $result], round(app()->getBeginTime(), 3));

        //返回登录信息
        return $result;
    }

    /**
     * 退出登录
     * @param $adminInfo
     * @return bool
     */
    public function logout($adminInfo)
    {
        //token不存在，不注销
        if (!isset($adminInfo['token'])) return false;

        //清空token
        return AdminTokenService::clearToken($adminInfo['id'], $adminInfo['token']);
    }

    /**
     * 登录检验
     * @param $account
     * @param $password
     * @return array|bool
     * @throws ValidateException
     */
    protected static function verify($account, $password)
    {
        //获取配置
        $admin_login = com_get_config('admin_login','core');

        //登录限制
        $config = [
            'is_login_limit' => $admin_login['is_login_limit'],
            'password_error_count' => $admin_login['password_error_count'],
            'limit_login_time' => $admin_login['limit_login_time'],
        ];

        $adminAccountSafeCache = new AdminAccountSafeCache();
        if ($config['is_login_limit'] == 1) {
            $adminAccountSafeCache->count = $config['password_error_count'];
            $adminAccountSafeCache->minute = $config['limit_login_time'];
        }

        //后台账号安全机制，连续输错后锁定，防止账号密码暴力破解
        if ($config['is_login_limit'] == 1 && !$adminAccountSafeCache->isSafe($account)) {
            throw new ValidateException('密码连续' . $adminAccountSafeCache->count . '次输入错误，请' . $adminAccountSafeCache->minute . '分钟后重试');
        }

        $adminInfo = Admin::where('account', '=', $account)
            ->hidden(['delete_time'])
            ->findOrEmpty();

        if (!$adminInfo) throw new ValidateException('账号不存在');

        if ($adminInfo['disable'] === 1) throw new ValidateException('账号已禁用');

        if (empty($adminInfo['password'])) {
            $adminAccountSafeCache->record($account);
            throw new ValidateException('账号不存在');
        }

        $passwordSalt = com_get_config('unique_identification','core');

        if ($adminInfo['password'] !== password_encrypt($password, $passwordSalt)) {
            $adminAccountSafeCache->record($account);
            throw new ValidateException('密码错误');
        }

        $adminAccountSafeCache->remove($account);

        $adminInfo['role_id'] = AdminRole::where('admin_id', $adminInfo['id'])->column('role_id');

        $roleName = '';
        $roleLists = SystemRole::column('name', 'id');
        if ($adminInfo['root'] == 1) {
            $roleName = '系统管理员';
        } else {
            foreach ($adminInfo['role_id'] as $roleId) {
                $roleName .= $roleLists[$roleId] ?? '';
                $roleName .= '/';
            }
            $roleName = trim($roleName, '/');
        }

        $adminInfo['role_name'] = $roleName;
        return $adminInfo;
    }
}